package com.example.demo.controller;

import com.example.demo.common.ResultAjax;
import com.example.demo.common.SessionUtils;
import com.example.demo.config.ThreadPoolConfig;
import com.example.demo.model.Articleinfo;
import com.example.demo.model.Userinfo;
import com.example.demo.model.vo.UserinfoVo;
import com.example.demo.service.ArticleService;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.websocket.Session;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;


@RestController
@RequestMapping("/art")
public class ArticleController {
    private static final int _DESC_LENGTH = 120; // 文章简介的长度

    @Autowired
    private ArticleService articleService;

    @Autowired
    private ThreadPoolTaskExecutor taskExecutor;

    @Autowired
    private UserService userService;

    /**
     * 得到当前用户文章列表
     */
    @RequestMapping("/mylist")
    public ResultAjax myList(HttpServletRequest request) {
        // 1、得当当前登录用户
        Userinfo userinfo = SessionUtils.getUser(request);
        if (userinfo == null) {
            return ResultAjax.fail(-1, "请先登录！");
        }
        // 2、根据用户id查询此用户发表的所哟文章
        List<Articleinfo> list = articleService.getListById(userinfo.getId());
        // 处理 list ，帮文章变成简介
        if (list != null && list.size() > 0) {
            // 并行处理list集合，这是一个规定写法，可以记下来，多操作
            list.stream().parallel().forEach((art) -> {
                if (art.getContent().length() > _DESC_LENGTH) {
                    art.setContent(art.getContent().substring(0, _DESC_LENGTH));
                }
            });
        }
        // 3、返回给前端
        return ResultAjax.succ(list);
    }

    /**
     * 删除文章操作
     */
    @RequestMapping("/del")
    public ResultAjax del(Integer aid, HttpServletRequest request) {
        // 1、参数效验
        if (aid == null || aid <= 0) {
            return ResultAjax.fail(-1, "参数错误！");
        }
        // 2、得到当前登录的用户
        Userinfo userinfo = SessionUtils.getUser(request);
        if (userinfo == null) {
            return ResultAjax.fail(-1, "请先登录");
        }
        // 3、判断文章的归属人并删除操作  where id=aid and uid=uid
        int result = articleService.del(aid, userinfo.getId());
        // 4.将结果返回给前端
        return ResultAjax.succ(result);
    }


    /**
     * 添加文章
     */
    @RequestMapping("/add")
    public ResultAjax add(Articleinfo articleinfo, HttpServletRequest request) {
        // 1、参数效验
        if (articleinfo == null || !StringUtils.hasLength(articleinfo.getTitle())
                || !StringUtils.hasLength(articleinfo.getContent())) {
            return ResultAjax.fail(-1, "非法参数！");
        }
        // 2、组装数据
        Userinfo userinfo = SessionUtils.getUser(request);
        if (userinfo == null) {
            return ResultAjax.fail(-2, "请先登录！");
        }
        articleinfo.setUid(userinfo.getId());

        // 3、将数据入库
        int result = articleService.add(articleinfo);
        // 4、将返回结果给前端
        return ResultAjax.succ(result);
    }

    /**
     * 查询自己的文章详情
     */
    @RequestMapping("/update_lnit")
    public ResultAjax updateInit(HttpServletRequest request, Integer aid) {
        //1、参数效验
        if (aid == null || aid <= 0) {
            return ResultAjax.fail(-1, "参数有误！");
        }
        //2、得到当前用户的id
        Userinfo userinfo = SessionUtils.getUser(request);
        if (userinfo == null) {
            return ResultAjax.fail(-2, "请先登录!");
        }
        //3、查询文章并效验权限 where id=#{id} and uid=#{uid}
        Articleinfo articleinfo = articleService.getArticleIdAndUid(aid, userinfo.getId());
        //4、将结果返回给前端
        return ResultAjax.succ(articleinfo);
    }


    /**
     * 修改文章信息
     */
    @RequestMapping("/update")
    public ResultAjax update(Articleinfo articleinfo, HttpServletRequest request) {
        //1、参数效验
        if (articleinfo == null || !StringUtils.hasLength(articleinfo.getTitle())
                || !StringUtils.hasLength(articleinfo.getContent())
                || articleinfo.getId() == 0) {
            return ResultAjax.fail(-1, "非法参数！");
        }
        //2、获取登录用户
        Userinfo userinfo = SessionUtils.getUser(request);
        if (userinfo == null) {
            return ResultAjax.fail(-2, "请先登录");
        }
        articleinfo.setUid(userinfo.getId());
        //3、执行修改操作并效验归属人
        //Service+sql
        int result = articleService.update(articleinfo);
        //4、将结果返回给前端
        return ResultAjax.succ(result);
    }

    /**
     * 查询文章详情页
     */
    @RequestMapping("/detail")
    public ResultAjax detail(Integer aid) throws ExecutionException, InterruptedException {
        // 1、参数效验
        if (aid == null || aid <= 0) {
            return ResultAjax.fail(-1, "非法参数！！！");
        }
        // 2、查询文章详情
        Articleinfo articleinfo = articleService.getDetailById(aid);
        if (articleinfo == null || articleinfo.getId() <= 0) {
            return ResultAjax.fail(-1, "非法参数！");
        }
        // 3,4步骤可以使用并发线程
        // 3、根据uid查询用户的详情
        FutureTask<UserinfoVo> userTask = new FutureTask(() -> {
            return userService.getUserById(articleinfo.getUid());

        });

        taskExecutor.submit(userTask);
        // 4、根据uid查询用户发表的总文章数
        FutureTask<Integer> artCountTask = new FutureTask<>(() -> {
            return articleService.getArtCountByUid(articleinfo.getUid());
        });
        taskExecutor.submit(artCountTask);
        // 5、组装数据
        UserinfoVo userinfoVo = userTask.get(); //等待任务（线程池）执行完成
        int artCount = artCountTask.get();// 等待任务（线程池）执行完成
        userinfoVo.setArtCount(artCount);// 数据的组装

        //需要把 userinfo 和 articleinfo 放到前端的结果里面
        HashMap<String, Object> map = new HashMap<>();
        map.put("user", userinfoVo);
        map.put("art", articleinfo);
        // 6、返回结果给前端
        return ResultAjax.succ(map);
    }


    /**
     * 阅读量加1
     */
    @RequestMapping("/increment_rcount")
    public ResultAjax incrementRCount(Integer aid) {
        // 1、效验参数
        if (aid == null || aid <= 0) {
            return ResultAjax.fail(-1, "参数错误！！");
        }

        // 2、更改数据库
        int result = articleService.incrementRCount(aid);
        // 3、返回结果
        return ResultAjax.succ(result);
    }


    /**
     * 查询分页功能
     */
    @RequestMapping("/getlistbypage")
    public ResultAjax getListByPage(Integer psize, Integer pindex) throws ExecutionException, InterruptedException {
        // 1、先参数矫正
        if (psize == null || psize < 1) {
            psize = 2;
        }
        if (pindex == null || pindex < 1) {
            pindex = 1; // 默认在第一页
        }
        // 2、多线程，并发进行文章列表和总页数的查询
        // 2.1 查询分页列表数据
        int offset = psize * (pindex - 1);
        int finalPsize = psize;
        FutureTask<List<Articleinfo>> listTask = new FutureTask<>(() -> {
            return articleService.getListByPage(finalPsize, offset);
        });
        // 2.2 查找总页数
        FutureTask<Integer> totalPage = new FutureTask<>(() -> {

            // 需要返回文章总数目
            int totalArtCount = articleService.getArtCount();
            //结果需要向上取整
            double sizeTemp = (totalArtCount * 1.0) / (finalPsize * 1.0);
            return (int) Math.ceil(sizeTemp);
        });
        taskExecutor.submit(listTask);
        taskExecutor.submit(totalPage);
        // 3、组装数据
        List<Articleinfo> list = listTask.get(); // 等待线程完成
        int totalSize = totalPage.get();// 等待线程完成

        // 需要一个结果放置
        HashMap<String, Object> result = new HashMap<>();
        result.put("list", list);
        result.put("size", totalSize);

        // 4、将结果返回给前端
        return ResultAjax.succ(result);
    }
}
